﻿using System;
using System.Threading.Tasks;

namespace IoCDemo
{
    class Program
    {
        static async Task Main()
        {
            while (true)
            {
                var address = new Uri("http://127.0.0.1:8080/api/test");
                await MvcLib.ListenAsync(address);
                while (true)
                {
                    var request = await MvcLib.ReceiceAsync();
                    var controller = await MvcLib.CreateControllerAsync(request);
                    var view = await MvcLib.ExecuteControllerAsync(controller);
                    await MvcLib.RenderViewAsync(view);
                }
            }
        }
    }

    public static class MvcLib
    {
        /// <summary>
        /// 启动一个监听器并将其绑定到指定的地址进行http请求的监听
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static Task ListenAsync(Uri address)
        {
            return Task.CompletedTask;
        }

        /// <summary>
        /// 接收抵达的请求
        /// </summary>
        /// <returns>接收到的请求</returns>
        public static Task<HttpContext> ReceiceAsync()
        {
            return Task.FromResult(new HttpContext());
        }

        /// <summary>
        /// 根据接收的请求解析并激活目标Controller对象
        /// </summary>
        /// <param name="request"></param>
        /// <returns>激活的Controller对象</returns>
        public static Task<Controller> CreateControllerAsync(HttpContext request)
        {
            return Task.FromResult(new Controller());
        }

        /// <summary>
        /// 执行激活的对象Controller，返回视图
        /// </summary>
        /// <param name="controller"></param>
        /// <returns>表示视图的对象</returns>
        public static Task<View> ExecuteControllerAsync(Controller controller)
        {
            return Task.FromResult(new View());
        }

        /// <summary>
        /// 将视图装换成html请求
        /// </summary>
        /// <param name="view"></param>
        /// <returns></returns>
        public static Task RenderViewAsync(View view)
        {
            return Task.CompletedTask;
        }

    }

    public class View { }

    public class Controller { }

    public class HttpContext { }


    #region 模板方法

    /// <summary>
    /// 将整个执行流程放到类中，在类中分别定义了5个虚方法。
    /// 模板方法StartAsync根据预定义的请求处理流程先后调用这5个方法。
    /// 在具体的应用场景中，只需要实例化MvcEngine，并调用StartAsync方法就可以满足基本要求
    /// </summary>
    public class MvcEngine
    {
        public async Task StartAsync(Uri address)
        {
            await ListenAsync(address);
            while (true)
            {
                var request = await ReceiceAsync();
                var controller = await CreateControllerAsync(request);
                var view = await ExecuteControllerAsync(controller);
                await RenderViewAsync(view);
            }
        }

        protected virtual Task ListenAsync(Uri address) => Task.CompletedTask;
        protected virtual Task<HttpContext> ReceiceAsync() => Task.FromResult(new HttpContext());
        protected virtual Task<Controller> CreateControllerAsync(HttpContext request) => Task.FromResult(new Controller());
        protected virtual Task<View> ExecuteControllerAsync(Controller controller) => Task.FromResult(new View());
        protected virtual Task RenderViewAsync(View view) => Task.CompletedTask;
    }

    /// <summary>
    /// 如果请求环节无法满足应用场景，可以创建派生类，并重写某个环节的虚方法即可。
    /// </summary>
    public class FoobarMvcEngine : MvcEngine
    {
        protected override Task<Controller> CreateControllerAsync(HttpContext request)
        {
            //此处省略了扩展实现

            return Task.FromResult(new Controller());
        }
    }

    #endregion

    #region 工厂方法

    /// <summary>
    /// 监听、接收和响应请求
    /// </summary>
    public interface IWebListener
    {
        Task ListenAsync(Uri address);
        Task<HttpContext> ReceiceAsync();
    }
    public class WebListener : IWebListener
    {
        public Task ListenAsync(Uri address) => Task.CompletedTask;
        public Task<HttpContext> ReceiceAsync() => Task.FromResult(new HttpContext());
    }

    /// <summary>
    /// 根据当前上下文激活目标Controller对象，并做一些释放回收的工作
    /// </summary>
    public interface IControllerActivator
    {
        Task<Controller> CreateControllerAsync(HttpContext request);
        Task ReleaseAsync(Controller controller);
    }
    public class ControllerActivator : IControllerActivator
    {
        public Task<Controller> CreateControllerAsync(HttpContext request) => Task.FromResult(new Controller());
        public Task ReleaseAsync(Controller controller) => Task.CompletedTask;
    }

    /// <summary>
    /// 针对Controller的执行
    /// </summary>
    public interface IControllerExecutor
    {
        Task<View> ExecuteAsync(Controller controller);
    }
    public class ControllerExecutor : IControllerExecutor
    {
        public Task<View> ExecuteAsync(Controller controller) => Task.FromResult(new View());
    }

    /// <summary>
    /// 视图的呈现
    /// </summary>
    public interface IViewRender
    {
        Task RenderViewAsync(View view);
    }
    public class ViewRender : IViewRender
    {
        public Task RenderViewAsync(View view) => Task.CompletedTask;
    }

    /// <summary>
    /// 采用默认的实现，实现预定的流程
    /// </summary>
    public class MvcEngine1
    {
        public async Task StartAsync(Uri address)
        {
            var listener = GetWebListener();
            var controllerActivator = GetControllerActivator();
            var controllerExecutor = GetControllerExecutor();
            var viewRender = GetIViewRender();

            await listener.ListenAsync(address);
            while (true)
            {
                var request = await listener.ReceiceAsync();
                var controller = await controllerActivator.CreateControllerAsync(request);
                try
                {
                    var view = await controllerExecutor.ExecuteAsync(controller);
                    await viewRender.RenderViewAsync(view);
                }
                finally
                {
                    await controllerActivator.ReleaseAsync(controller);
                }

            }
        }

        protected virtual IWebListener GetWebListener() => new WebListener();
        protected virtual IControllerActivator GetControllerActivator() => new ControllerActivator();
        protected virtual IControllerExecutor GetControllerExecutor() => new ControllerExecutor();
        protected virtual IViewRender GetIViewRender() => new ViewRender();
    }

    /// <summary>
    /// 定制化的IControllerActivator流程
    /// 需要根据需要实现接口
    /// </summary>
    public class ControllerExActivator : IControllerActivator
    {
        public Task<Controller> CreateControllerAsync(HttpContext request)
        {
            //省略实现

            return Task.FromResult(new Controller());
        }
        public Task ReleaseAsync(Controller controller)
        {
            //省略实现

            return Task.CompletedTask;
        }
    }

    /// <summary>
    /// 如果请求环节无法满足应用场景，可以创建派生类，并重写某个环节的工厂方法即可。
    /// </summary>
    public class FoobarMvcEngine1 : MvcEngine1
    {
        protected override IControllerActivator GetControllerActivator()
        {
            return new ControllerExActivator();
        }
    }

    #endregion

    #region 抽象工厂

    /// <summary>
    /// 抽象工厂会创建多个实例
    /// </summary>
    public interface IMvcEngineFactory
    {
        IWebListener GetWebListener();
        IControllerActivator GetControllerActivator();
        IControllerExecutor GetControllerExecutor();
        IViewRender GetIViewRender();
    }
    /// <summary>
    /// 默认实现
    /// </summary>
    public class MvcEngineFactory : IMvcEngineFactory
    {
        public virtual IWebListener GetWebListener() => new WebListener();
        public virtual IControllerActivator GetControllerActivator() => new ControllerActivator();
        public virtual IControllerExecutor GetControllerExecutor() => new ControllerExecutor();
        public virtual IViewRender GetIViewRender() => new ViewRender();
    }

    /// <summary>
    /// 采用默认的实现，实现预定的流程
    /// </summary>
    public class MvcEngine2
    {
        public IMvcEngineFactory _engineFactory { get; }

        public MvcEngine2(IMvcEngineFactory engineFactory)
        {
            _engineFactory = engineFactory ?? new MvcEngineFactory();
        }

        public async Task StartAsync(Uri address)
        {
            var listener = _engineFactory.GetWebListener();
            var controllerActivator = _engineFactory.GetControllerActivator();
            var controllerExecutor = _engineFactory.GetControllerExecutor();
            var viewRender = _engineFactory.GetIViewRender();

            await listener.ListenAsync(address);
            while (true)
            {
                var request = await listener.ReceiceAsync();
                var controller = await controllerActivator.CreateControllerAsync(request);
                try
                {
                    var view = await controllerExecutor.ExecuteAsync(controller);
                    await viewRender.RenderViewAsync(view);
                }
                finally
                {
                    await controllerActivator.ReleaseAsync(controller);
                }

            }
        }
    }

    /// <summary>
    /// 如果请求环节无法满足应用场景，可以创建派生类，并重写某个环节的虚方法即可。
    /// </summary>
    public class FoobarMvcEngineFactory : MvcEngineFactory
    {
        public override IControllerActivator GetControllerActivator()
        {
            return new ControllerExActivator();
        }
    }


    #endregion

}
